]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
extensionPrefs: Support extension updates
authorFlorian Müllner <fmuellner@gnome.org>
Sat, 30 Nov 2019 14:20:04 +0000 (15:20 +0100)
committerFlorian Müllner <fmuellner@gnome.org>
Mon, 3 Feb 2020 18:33:12 +0000 (19:33 +0100)
Now that we have support for extension updates in the shell, we
need some place to display the updates to the user.

As we are establishing the Extensions app as the primary way for
managing extensions, it's a natural place for that functionality.

Show which extensions have updates available, and offer a log out
button (so gnome-shell can apply the updates when logging back in).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1968

js/extensionPrefs/css/application.css
js/extensionPrefs/main.js
js/extensionPrefs/ui/extension-row.ui
js/extensionPrefs/ui/extensions-window.ui

index 1a35205f1d5fecb1243049ed8e0a7d4d4ecf02dc..37105d08191dd9e5c7e436f3eab07cbc9a945749 100644 (file)
@@ -7,3 +7,5 @@
 .details-button.expanded:dir(rtl) image {
   -gtk-icon-transform: rotate(-0.25turn);
 }
+
+image.warning { color: @warning_color; }
index f8ce4fb7ae4cee57b431e7ee0129c062bef88dec..67ff6c5c1578b50898be1df02732ade0d366d56d 100644 (file)
@@ -86,6 +86,8 @@ var ExtensionsWindow = GObject.registerClass({
         'mainBox',
         'mainStack',
         'scrolledWindow',
+        'updatesBar',
+        'updatesLabel',
     ],
 }, class ExtensionsWindow extends Gtk.ApplicationWindow {
     _init(params) {
@@ -94,6 +96,7 @@ var ExtensionsWindow = GObject.registerClass({
         this._startupUuid = null;
         this._loaded = false;
         this._prefsDialog = null;
+        this._updatesCheckId = 0;
 
         this._mainBox.set_focus_vadjustment(this._scrolledWindow.vadjustment);
 
@@ -102,6 +105,10 @@ var ExtensionsWindow = GObject.registerClass({
         action.connect('activate', this._showAbout.bind(this));
         this.add_action(action);
 
+        action = new Gio.SimpleAction({ name: 'logout' });
+        action.connect('activate', this._logout.bind(this));
+        this.add_action(action);
+
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
         this._settings.bind('disable-user-extensions',
             this._killSwitch, 'active',
@@ -219,6 +226,22 @@ var ExtensionsWindow = GObject.registerClass({
         aboutDialog.present();
     }
 
+    _logout() {
+        this.application.get_dbus_connection().call(
+            'org.gnome.SessionManager',
+            '/org/gnome/SessionManager',
+            'org.gnome.SessionManager',
+            'Logout',
+            new GLib.Variant('(u)', [0]),
+            null,
+            Gio.DBusCallFlags.NONE,
+            -1,
+            null,
+            (o, res) => {
+                o.call_finish(res);
+            });
+    }
+
     _buildErrorUI(row, exc) {
         let scroll = new Gtk.ScrolledWindow({
             hscrollbar_policy: Gtk.PolicyType.NEVER,
@@ -357,6 +380,8 @@ var ExtensionsWindow = GObject.registerClass({
         let extension = ExtensionUtils.deserializeExtension(newState);
         let row = this._findExtensionRow(uuid);
 
+        this._queueUpdatesCheck();
+
         // the extension's type changed; remove the corresponding row
         // and reset the variable to null so that we create a new row
         // below and add it to the appropriate list
@@ -403,6 +428,29 @@ var ExtensionsWindow = GObject.registerClass({
             this._systemList.add(row);
     }
 
+    _queueUpdatesCheck() {
+        if (this._updatesCheckId)
+            return;
+
+        this._updatesCheckId = GLib.timeout_add_seconds(
+            GLib.PRIORITY_DEFAULT, 1, () => {
+                this._checkUpdates();
+
+                this._updatesCheckId = 0;
+                return GLib.SOURCE_REMOVE;
+            });
+    }
+
+    _checkUpdates() {
+        let nUpdates = this._userList.get_children().filter(c => c.hasUpdate).length;
+
+        this._updatesLabel.label = Gettext.ngettext(
+            '%d extension will be updated on next login.',
+            '%d extensions will be updated on next login.e',
+            nUpdates).format(nUpdates);
+        this._updatesBar.visible = nUpdates > 0;
+    }
+
     _extensionsLoaded() {
         this._userList.visible = this._userList.get_children().length > 0;
         this._systemList.visible = this._systemList.get_children().length > 0;
@@ -412,6 +460,8 @@ var ExtensionsWindow = GObject.registerClass({
         else
             this._mainStack.visible_child_name = 'placeholder';
 
+        this._checkUpdates();
+
         if (this._startupUuid)
             this._showPrefs(this._startupUuid);
         this._startupUuid = null;
@@ -526,6 +576,7 @@ var ExtensionRow = GObject.registerClass({
         'descriptionLabel',
         'versionLabel',
         'authorLabel',
+        'updatesIcon',
         'revealButton',
         'revealer',
     ],
@@ -622,6 +673,10 @@ var ExtensionRow = GObject.registerClass({
         return this._extension.hasPrefs;
     }
 
+    get hasUpdate() {
+        return this._extension.hasUpdate || false;
+    }
+
     get type() {
         return this._extension.type;
     }
@@ -645,6 +700,8 @@ var ExtensionRow = GObject.registerClass({
         action.set_state(new GLib.Variant('b', state));
         action.enabled = this._canToggle();
 
+        this._updatesIcon.visible = this.hasUpdate;
+
         this._versionLabel.label = `${this.version}`;
         this._versionLabel.visible = this.version !== '';
 
index c4f4e60507ff8bdde4d0912cebb49b1805b2e4da..f54ab3c760e1819da5133263fc172a1c9ea10c25 100644 (file)
         <child>
           <object class="GtkLabel" id="nameLabel">
             <property name="visible">True</property>
+          </object>
+        </child>
+        <child>
+          <object class="GtkImage" id="updatesIcon">
+            <property name="no_show_all">True</property>
+            <property name="icon_name">software-update-available-symbolic</property>
+            <style>
+              <class name="warning"/>>
+            </style>
+          </object>
+        </child>
+        <child>
+          <object class="GtkLabel">
+            <property name="visible">True</property>
             <property name="hexpand">True</property>
-            <property name="halign">start</property>
           </object>
         </child>
         <child>
           <packing>
             <property name="left_attach">0</property>
             <property name="top_attach">1</property>
-            <property name="width">5</property>
+            <property name="width">7</property>
           </packing>
         </child>
       </object>
index 3d211395f00c0677d3181c960e1073d86ed208cb..c288bb37110c46e1587b5a3036ff76481b5ca2b3 100644 (file)
       </object>
     </child>
     <child>
-      <object class="GtkStack" id="mainStack">
+      <object class="GtkBox">
         <property name="visible">True</property>
-        <property name="transition_type">crossfade</property>
+        <property name="orientation">vertical</property>
         <child>
-          <object class="GtkScrolledWindow" id="scrolledWindow">
+          <object class="GtkStack" id="mainStack">
             <property name="visible">True</property>
-            <property name="hscrollbar_policy">never</property>
+            <property name="transition_type">crossfade</property>
+            <property name="vexpand">True</property>
             <child>
-              <object class="GtkViewport">
+              <object class="GtkScrolledWindow" id="scrolledWindow">
                 <property name="visible">True</property>
+                <property name="hscrollbar_policy">never</property>
                 <child>
-                  <object class="GtkBox" id="mainBox">
+                  <object class="GtkViewport">
                     <property name="visible">True</property>
-                    <property name="orientation">vertical</property>
-                    <property name="halign">center</property>
-                    <property name="margin">36</property>
-                    <property name="spacing">12</property>
-                    <child>
-                      <object class="GtkLabel">
-                        <property name="visible"
-                                  bind-source="userList"
-                                  bind-property="visible"
-                                  bind-flags="sync-create"/>
-                        <property name="halign">start</property>
-                        <property name="hexpand">True</property>
-                        <property name="label" translatable="yes">Manually Installed</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkListBox" id="userList">
-                        <property name="visible">True</property>
-                        <property name="selection_mode">none</property>
-                        <property name="margin_bottom">24</property>
-                        <style>
-                          <class name="frame"/>
-                        </style>
-                      </object>
-                    </child>
                     <child>
-                      <object class="GtkLabel">
-                        <property name="visible"
-                                  bind-source="systemList"
-                                  bind-property="visible"
-                                  bind-flags="sync-create"/>
-                        <property name="halign">start</property>
-                        <property name="hexpand">True</property>
-                        <property name="label" translatable="yes">Built-In</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
-                      </object>
-                    </child>
-                    <child>
-                      <object class="GtkListBox" id="systemList">
+                      <object class="GtkBox" id="mainBox">
                         <property name="visible">True</property>
-                        <property name="selection_mode">none</property>
-                        <style>
-                          <class name="frame"/>
-                        </style>
+                        <property name="orientation">vertical</property>
+                        <property name="halign">center</property>
+                        <property name="margin">36</property>
+                        <property name="spacing">12</property>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible"
+                                      bind-source="userList"
+                                      bind-property="visible"
+                                      bind-flags="sync-create"/>
+                            <property name="halign">start</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Manually Installed</property>
+                            <attributes>
+                              <attribute name="weight" value="bold"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkListBox" id="userList">
+                            <property name="visible">True</property>
+                            <property name="selection_mode">none</property>
+                            <property name="margin_bottom">24</property>
+                            <style>
+                              <class name="frame"/>
+                            </style>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible"
+                                      bind-source="systemList"
+                                      bind-property="visible"
+                                      bind-flags="sync-create"/>
+                            <property name="halign">start</property>
+                            <property name="hexpand">True</property>
+                            <property name="label" translatable="yes">Built-In</property>
+                            <attributes>
+                              <attribute name="weight" value="bold"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkListBox" id="systemList">
+                            <property name="visible">True</property>
+                            <property name="selection_mode">none</property>
+                            <style>
+                              <class name="frame"/>
+                            </style>
+                          </object>
+                        </child>
                       </object>
                     </child>
                   </object>
                 </child>
               </object>
+              <packing>
+                <property name="name">main</property>
+              </packing>
             </child>
-          </object>
-          <packing>
-            <property name="name">main</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="orientation">vertical</property>
-            <property name="margin">32</property>
-            <property name="spacing">6</property>
-            <property name="valign">center</property>
             <child>
-              <object class="GtkImage">
+              <object class="GtkBox">
                 <property name="visible">True</property>
-                <property name="pixel_size">96</property>
-                <property name="icon_name">org.gnome.Extensions-symbolic</property>
+                <property name="orientation">vertical</property>
+                <property name="margin">32</property>
+                <property name="spacing">6</property>
+                <property name="valign">center</property>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">True</property>
+                    <property name="pixel_size">96</property>
+                    <property name="icon_name">org.gnome.Extensions-symbolic</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">No Installed Extensions</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                      <attribute name="scale" value="1.44"/>
+                    </attributes>
+                  </object>
+                </child>
               </object>
+              <packing>
+                <property name="name">placeholder</property>
+              </packing>
             </child>
             <child>
-              <object class="GtkLabel">
+              <object class="GtkBox">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">No Installed Extensions</property>
-                <attributes>
-                  <attribute name="weight" value="bold"/>
-                  <attribute name="scale" value="1.44"/>
-                </attributes>
+                <property name="margin_left">100</property>
+                <property name="margin_right">100</property>
+                <property name="margin_top">100</property>
+                <property name="margin_bottom">60</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Something’s gone wrong</property>
+                    <attributes>
+                      <attribute name="scale" value="1.44"/>
+                    </attributes>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">We’re very sorry, but it was not possible to get the list of installed extensions. Make sure you are logged into GNOME and try again.</property>
+                    <property name="justify">center</property>
+                    <property name="wrap">True</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                </child>
               </object>
+              <packing>
+                <property name="name">noshell</property>
+              </packing>
             </child>
           </object>
-          <packing>
-            <property name="name">placeholder</property>
-          </packing>
         </child>
         <child>
-          <object class="GtkBox">
-            <property name="visible">True</property>
-            <property name="margin_left">100</property>
-            <property name="margin_right">100</property>
-            <property name="margin_top">100</property>
-            <property name="margin_bottom">60</property>
-            <property name="orientation">vertical</property>
-            <property name="spacing">12</property>
+          <object class="GtkActionBar" id="updatesBar">
+            <property name="no_show_all">True</property>
             <child>
-              <object class="GtkLabel">
+              <object class="GtkImage">
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">Something’s gone wrong</property>
-                <attributes>
-                  <attribute name="scale" value="1.44"/>
-                </attributes>
+                <property name="pixel-size">24</property>
+                <property name="margin">6</property>
+                <property name="icon_name">software-update-available-symbolic</property>
                 <style>
-                  <class name="dim-label"/>
+                  <class name="warning"/>>
                 </style>
               </object>
             </child>
             <child>
-              <object class="GtkLabel">
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="halign">start</property>
+                    <property name="label">Extension Updates Ready</property>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                    </attributes>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="updatesLabel">
+                    <property name="visible">True</property>
+                    <property name="halign">start</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="yes">Logout…</property>
                 <property name="visible">True</property>
-                <property name="label" translatable="yes">We’re very sorry, but it was not possible to get the list of installed extensions. Make sure you are logged into GNOME and try again.</property>
-                <property name="justify">center</property>
-                <property name="wrap">True</property>
+                <property name="valign">center</property>
+                <property name="action-name">win.logout</property>
+                <property name="receives_default">True</property>
                 <style>
-                  <class name="dim-label"/>
+                  <class name="suggested-action"/>
                 </style>
               </object>
+              <packing>
+                <property name="pack_type">end</property>
+              </packing>
             </child>
           </object>
-          <packing>
-            <property name="name">noshell</property>
-          </packing>
         </child>
       </object>
     </child>